package com.it.gmall.activity.service;

import com.alibaba.nacos.common.util.Md5Utils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.it.gmall.activity.mapper.ActivityMapper;
import com.it.gmall.activity.redis.CacheHelper;
import com.it.gmall.activity.utils.DateUtil;
import com.it.gmall.common.constant.RedisConst;
import com.it.gmall.common.util.MD5;
import com.it.gmall.model.activity.SeckillGoods;
import com.it.gmall.model.activity.UserRecode;
import com.it.gmall.mq.consts.MqConst;
import com.it.gmall.mq.service.SendMsgService;
import org.apache.commons.codec.digest.Md5Crypt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Service
public class ActivityServiceImpl implements ActivityService{
    @Autowired
    private ActivityMapper activityMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SendMsgService sendMsgService;

    // 定时添加秒杀商品
    @Override
    public void activityAddSeckillGoods() {
        /*
        * 查询条件：
        * 1.审核通过 status = 1
        * 2.有库存 stock_count > 0
        * 3.在秒杀当天时间范围之内的
        * select * from seckill_goods where `status` = 1 and stock_count > 0 and date(start_time)='2021-12-7'
        */
        QueryWrapper<SeckillGoods> wrapper = new QueryWrapper<>();
        wrapper.eq("status",1)
                .gt("stock_count",0)
                .eq("date(start_time)", DateUtil.formatDate(new Date()));
        List<SeckillGoods> seckillGoods = activityMapper.selectList(wrapper);

        if(!CollectionUtils.isEmpty(seckillGoods))
            // 压入缓存 map h = {hk,hv}  => seckill:goods={商品skuId,商品本身}
            for (SeckillGoods seckillGood : seckillGoods) {
                // 如果不存在当前商品 在放入
                if(!redisTemplate.opsForHash().hasKey(RedisConst.SECKILL_GOODS, seckillGood.getSkuId().toString())){
                    // 将商品在半夜放入redis中预热 因为redis比MySQL快 秒杀要求快
                    redisTemplate.opsForHash().put(
                            RedisConst.SECKILL_GOODS,seckillGood.getSkuId().toString(),seckillGood);
                    // 当前商品剩余的库存
                    Integer stockCount = seckillGood.getStockCount();

                    /*秒杀要求快：防止超卖
                     * 防止超卖：分布式锁 但是很慢
                     * 解决：
                     * 将商品本身放到redis得list中,即商品的每一个skuId，而不是商品的剩余数量
                     * seckill:stock:skuId*/
                    Long[] skuIds = new Long[stockCount];
                    for (int i = 0; i < skuIds.length; i++) {
                        skuIds[i] = seckillGood.getSkuId();
                    }
                    redisTemplate.opsForList().leftPushAll(
                            RedisConst.SECKILL_STOCK_PREFIX+seckillGood.getSkuId(),skuIds);

                    // 状态位 0:有货 1:无货
                    /*redis的发布订阅
                    *需要保证每个秒杀微服务都接收到消息*/
                    redisTemplate.convertAndSend("seckillpush",seckillGood.getSkuId()+":0");
                }

            }
        }

    // 获取首页显示数据
    @Override
    public List<SeckillGoods> getIndexGoods() {
        return redisTemplate.opsForHash().values(RedisConst.SECKILL_GOODS);
    }

    // 获取秒杀商品详情
    @Override
    public SeckillGoods item(Long skuId) {
        return (SeckillGoods) redisTemplate.opsForHash().get(RedisConst.SECKILL_GOODS,skuId.toString());
    }

    // 开始抢购
    @Override
    public void seckillOrder(Long skuId, String skuIdStr,String userId) {

        // 发消息的实体类
        UserRecode userRecode = new UserRecode();
        userRecode.setSkuId(skuId);
        userRecode.setUserId(userId);
        // 发送mq消息 (排队)
        sendMsgService.sendMsg(MqConst.EXCHANGE_DIRECT_SECKILL_USER,MqConst.ROUTING_SECKILL_USER,userRecode);
    }
}


